﻿using System;
using System.Security.Principal;
using System.Collections.Generic;
using System.DirectoryServices;
using System.Diagnostics;
using System.Threading;
using System.Collections.ObjectModel;
using System.Configuration;
using Microsoft.InformationSecurity.CISF.Security.Principal;
using Microsoft.InformationSecurity.CISF.Security.AuthZServices;
using AuthZServicesTest.AuthZServiceReference;

namespace AuthZServicesTest
{
    class AuthZServiceTest
    {
        #region Private Variables
        private enum Test_It
        {
            Get_Role_Members = 1,
            CISFPrincipal_Gets_Identity
        }
        static Stopwatch stopWatch = new Stopwatch();

        #endregion

        #region Main
        static void Main(string[] args)
        {
            Console.WriteLine("\nSelect which test to run.");
            Console.WriteLine("1 - Get all Users associated to a role.");
            Console.WriteLine("2 - Get User and Role information for a user.");
            Console.Write("\nEnter 1 or 2 (Ctrl c to end):  ");
            int test;

            if (Int32.TryParse(Console.ReadLine(), out test))
            {
                try
                {
                    bool endWhile = false;
                    while (0 < 1)
                    {
                        switch ((Test_It)test)
                        {
                            case Test_It.Get_Role_Members:
                                Test_Get_Role_Members();
                                break;

                            case Test_It.CISFPrincipal_Gets_Identity:
                                Test_CISFPrincipal_Gets_Identity();
                                break;

                            default:
                                Console.WriteLine("Invalid test option selected.");
                                endWhile = true;
                                break;
                        }

                        if (endWhile)
                            break;
                    }

                }

                #region Catch
                catch (Exception e)
                {
                    Console.WriteLine("An error occurred: '{0}'", e.Message);
                    Console.WriteLine("Source: '{0}'", e.Source);
                    Console.WriteLine("Stack Trace: '{0}'", e.StackTrace);
                }
                finally
                {
                    Console.ReadLine();
                }
                #endregion

            }
        }

        #endregion

        #region Test_Get_Role_Members
        /// <summary>
        /// Uses the AuthZServiceReference to get all members associated to a role.
        /// </summary>
        private static void Test_Get_Role_Members()
        {
            Console.Write("\n\nEnter a role (Ctrl c to end):  ");
            String role = Console.ReadLine();

            stopWatch.Reset();
            stopWatch.Start();

            AuthZServiceClient client = new AuthZServiceClient();

            User[] people = client.GetUsersInRole(role);

            stopWatch.Stop();

            if (people == null)
                Console.WriteLine("\n\nWhat the heck did you type in!");
            else
                if (people.Length > 0)
                {
                    Console.WriteLine();
                    foreach (User person in people)
                        Console.WriteLine("\nPersonId: {0}, FullName: {1}", person.PersonId, person.FullName);

                    Console.WriteLine("\n\nCount of users:  {0}", people.Length);
                }
                else
                    Console.WriteLine("\n\nAin't no users in the role!");

            Console.WriteLine("\nElapsed time in seconds:  {0}", stopWatch.Elapsed.TotalSeconds.ToString());
        }

        #endregion

        #region Test_CISFPrincipal_Gets_Identity
        /// <summary>
        /// Loads the current Windows Identity into CISFIdentity and checks which
        /// roles the user is a member of.
        /// </summary>
        private static void Test_CISFPrincipal_Gets_Identity()
        {
            CISFPrincipal principal = GetPrincipal();

            if (principal.CISFIdentity != null)
            {
                Console.WriteLine("\nElapsed time in seconds: {0}", stopWatch.Elapsed.TotalSeconds.ToString());

                Console.WriteLine("\nName: {0}", principal.CISFIdentity.Name);
                Console.WriteLine("Domain: {0}", principal.CISFIdentity.Domain);
                Console.WriteLine("sAMAccountName: {0}", principal.CISFIdentity.Alias);
                Console.WriteLine("Display Name: {0}", principal.CISFIdentity.DisplayName);
                Console.WriteLine("Full Name: {0}", principal.CISFIdentity.FullName);
                Console.WriteLine("PersonId: {0}", principal.CISFIdentity.PersonId);

                Console.WriteLine("\nIs in role SysAdmin?  {0}", principal.IsInRole("SysAdmin"));
                Console.WriteLine("Is in role Risk Manager?  {0}", principal.IsInRole("Risk Manager"));
                Console.WriteLine("Is in role Risk User?  {0}", principal.IsInRole("Risk User"));
                Console.WriteLine("Is in role Task Admin?  {0}", principal.IsInRole("Task Admin"));
                Console.WriteLine("Is in role Task Manager?  {0}", principal.IsInRole("Task Manager"));
                Console.WriteLine("Is in role Trusted Task User?  {0}", principal.IsInRole("Trusted Task User"));
                Console.WriteLine("Is in role Task User?  {0}", principal.IsInRole("Task User"));
                Console.WriteLine("Is in role Controls Manager?  {0}", principal.IsInRole("Controls Manager"));
                Console.WriteLine("Is in role Test Manager?  {0}", principal.IsInRole("Test Manager"));
                Console.WriteLine("Is in role Tester?  {0}", principal.IsInRole("Tester"));
                Console.WriteLine("Is in role Grunt?  {0}", principal.IsInRole("Grunt"));
            }
            else
            {
                Console.WriteLine("An identity object was not created due to invalid IIdentity argument.");
            }
        }

        #endregion

        #region GetUserInfo
        /// <summary>
        /// todo
        /// </summary>
        /// <returns></returns>
        private static User GetUserInfo(string name)
        {
            AuthZServiceClient client = new AuthZServiceClient();

            User user = client.GetUserInformation(name);

            stopWatch.Stop();

            if (user == null)
                return null;

            return user;
        }

        #endregion

        #region GetPrincipal
        private static CISFPrincipal GetPrincipal()
        {
            Console.WriteLine("\nPress enter for current logged in user");
            Console.Write("or enter a user's alias (Ctrl c to end):  ");
            String name = Console.ReadLine();

            IIdentity identity;

            if (String.IsNullOrEmpty(name))
                identity = WindowsIdentity.GetCurrent();
            else
                identity = new InvalidIdentity(name, "Kerberos", true);

            stopWatch.Reset();
            stopWatch.Start();
            return new CISFPrincipal(identity, GetUserInfo(identity.Name));
        }

        #endregion

    }
}
